#ifndef MODULES_CORE_REPOSITORYSERVICE_H_
#define MODULES_CORE_REPOSITORYSERVICE_H_
#include "../common.h"

#ifdef CONFIG_OPEN_SD__
#include <SD.h>
#else
#include <SPIFFS.h>
#endif

#define ENTITY_INJECTION_ID_AND_REPOSITORY(_id) \
	std::string id = _id;			\
	std::string getId() {	 \
		return id; 			\
	};\
	void save() {\
		RepositoryService * service = GET_BEAN(MODEL_REPOSITORY,RepositoryService);\
		service->save(*this);\
	}\
 	void load() {\
		RepositoryService * service = GET_BEAN(MODEL_REPOSITORY,RepositoryService);\
		service->load(*this);\
	}

class IEntity {
public:
	virtual ~IEntity() = default;
	virtual std::string getId();
	virtual void save();
	virtual void load();
	virtual String toPath() {
		String id = this->getId().c_str();
		return "/" + id;
	}
};

class RepositoryService: public IBean {
private:
	bool canOpen = false;
	FS *fs;
	FS* getFs() {
#ifdef CONFIG_OPEN_SD__
		return &SD;
#else
		return &SPIFFS;
#endif
	}
public:
	void prepare0() {
		open();
	}
	void open() {
#ifdef CONFIG_OPEN_SD__
		if (!SD.begin()) {
			Serial.println("error sd");
			return;
		}
		fs = &SD;
#else
			if (!SPIFFS.begin(true)) {
				Serial.println("error SPIFFS ");
				return;
			}
			fs = &SPIFFS;
	#endif
		Serial.println("Repository begin");
		this->canOpen = true;
	}

	void close() {
		if (!canOpen) {
			return;
		}
		Serial.println("Repository close ");
#ifdef CONFIG_OPEN_SD__
		SD.end();
#else
		SPIFFS.end();
#endif
	}
	void load(String &ret, String path) {
		if (!canOpen) {
			return;
		}
		Serial.print("load:");
		Serial.println(path);
		File f = fs->open(path, FILE_READ);
		const size_t len = f.size();
		if (len <= 0) {
			f.close();
			return;
		}
		char _bytes[len];
		//过滤后面内容 优化 readString 因为里面实现是每次扩容2byte ....不停复制
		int i = 0;
		int c = 0;
		while ((c = f.read()) > 0) {
			_bytes[i++] = c;
		}
		f.close();
		//加结束标志
		_bytes[i] = '\0';
		ret = _bytes;
	}

	void save(String ret, String path) {
		if (!canOpen) {
			return;
		}
		Serial.print("save:");
		Serial.println(path);
		File f = fs->open(path, FILE_WRITE);
		f.print(ret);
		f.close();
	}
	bool remove(String path) {
		if (!canOpen) {
			return false;
		}
		Serial.print("remove:");
		Serial.println(path);
		return fs->remove(path);
	}
	template<typename T>
	void load(T &obj) {
		if (!this->canOpen) {
			return;
		}
		//子类转父亲，强转必须是指针 不能直接转 ((IEntity) obj)
		IEntity *entity = (IEntity*) &obj;
		if (entity->getId().empty()) {
			Serial.print("entity id is empty");
			return;
		}
		String path = entity->toPath();
		String str;
		load(str, path);
		std::string _s = str.c_str();
		if (_s.empty()) {
			return;
		}

		try {
			aigc::JsonHelper::JsonToObject(obj, _s);
		} catch (...) {
			Serial.println("json error: " + str);
		}
	}

	template<typename T>
	void save(T &obj) {
		Serial.println(this->canOpen);
		if (!this->canOpen) {
			return;
		}
		String path = ((IEntity*) &obj)->toPath();
		String str;
		try {
			aigc::JsonHelper::ObjectToJson(obj, str);
			save(str, path);
		} catch (...) {
			Serial.println("json error: " + str);
		}
	}
};

#endif /* MODULES_CORE_REPOSITORYSERVICE_H_ */
